package com.woniuxy.lab.woniu_lab_boss.util;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.CreateNetworkResponse;
import com.github.dockerjava.api.command.InspectContainerResponse;
import com.github.dockerjava.api.exception.NotFoundException;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.netty.NettyDockerCmdExecFactory;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

@Slf4j
public class DockerCilentUtil {



    static final String DOCKER_HOST = "43.136.98.253";
    static final String DOCKER_PORT = "5732";


    private static final String DOCKER_API_VERSION = "1.38";
    /** 高版本的 docker-java
     * 开启docker连接
     * @return docker对象
     */
//    public static DockerClient getDockerClient(){
//        log.info("创建docker连接");
//        DefaultDockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
//                .withApiVersion(DOCKER_API_VERSION)
//                .withDockerHost("tcp://"+DOCKER_HOST+":2375")
//                .build();
//        //创建DockerHttpClient
//        DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
//                .dockerHost(config.getDockerHost())
//                .maxConnections(100)
//                .connectionTimeout(Duration.ofSeconds(3000))
//                .responseTimeout(Duration.ofSeconds(4500))
//                .build();
//
//
//        return  DockerClientImpl.getInstance(config, httpClient);
//    }
    public static DockerClient getDockerClient(){
        DockerClientConfig customConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost("tcp://" + DOCKER_HOST + ":" + DOCKER_PORT)
                .withDockerTlsVerify(false)
                .build();
        DockerClient dockerClient = DockerClientBuilder.getInstance(customConfig)
                .withDockerCmdExecFactory(new NettyDockerCmdExecFactory())
                .build();
        log.info("连接成功");
        return dockerClient;

    }
    /**
     *  关闭docker连接
     * @param dockerClient docker对象
     */
    public static void closeDocker(DockerClient dockerClient){
        log.info("关闭docker连接");

        try {
            dockerClient.close();
        } catch (IOException e) {
            //todo 异常需要改
            throw new RuntimeException(e);
        }
    }

    /**
     *  通过容器名返回容器对象
     * @param name 容器名
     * @return 容器对象
     */
    public static Container getContainerByName(DockerClient dockerClient,String name){


        Container container = null;
        List<Container> containerList = dockerClient.listContainersCmd().withShowAll(true).exec();
        for (Container c : containerList) {
            System.out.println(c.getNames()[0]);
            if (c.getNames()[0].equals("/"+name)){
                container=c;
                break;
            }
        }
        return container;
    }

    /**
     * 启动暂停中的容器
     * @param id dockerId
     * @return 启动状态
     */
    public static Boolean startContainerById(DockerClient dockerClient,String id){

        try {
            dockerClient.startContainerCmd(id).exec();
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 删除容器
     * @param id 容器id
     * @return 成功状态
     */
    private static Boolean rmContainerById(DockerClient dockerClient,String id){
        try {
            dockerClient.removeContainerCmd(id).exec();
        } catch (NotFoundException e) {
            return false;
        } finally {
            closeDocker(dockerClient);
        }
        return true;
    }

    /**
     * 构建镜像
     * @param imageName 镜像
     * @param imageTag 镜像的版本
     * @param path dockerFile路径
     * @return 镜像id
     */
//    public static String buildImage(DockerClient client,String imageName,String imageTag,String path) throws FileNotFoundException {
//
//        ImmutableSet<String> tag = ImmutableSet.of(imageName + ":" + imageTag);
//        FileInputStream fileInputStream = new FileInputStream(path);
//        System.out.println(fileInputStream);
//        String imageId = client.buildImageCmd(fileInputStream)
//                .withTags(tag)
//
//                .awaitImageId();
//        closeDocker(client);
//        return imageId;
//    }


    /**
     *  创建容器 不是run是create
     * @param image 镜像名称+版本 redis:latest
     * @param CPort docker端口 -p
     * @param LPort 映射的linux端口 -p
     * @param name --name 名称
     * @param env 环境变量 -e
     * @param networkName 网络名 -h
     * @param LPath 服务路径
     * @param CPath 容器路径
     * @return 创建的容器对象
     */
    public static CreateContainerResponse createContainer(DockerClient client,String image,Integer CPort,Integer LPort,String name,
                                                          String env, String networkName,String LPath,String CPath) {
        HostConfig hostConfig = new HostConfig().
                withPortBindings(PortBinding.parse(""+LPort+":"+CPort)).
                    withAutoRemove(true).withMemory(256 * 1024 * 1024L).withCpuCount(256L);
        if (CPath!=null && LPath!=null){
            hostConfig.withBinds(new Bind(LPath,new Volume(CPath)));
        }
        CreateContainerCmd containerCmd = client.createContainerCmd(image).withName(name)
                .withHostConfig(hostConfig);

        if (env!=null){
            containerCmd.withEnv(env);
        }
        if (networkName!=null){
            containerCmd.withHostName(networkName);
        }
        //创建
        CreateContainerResponse response = containerCmd.exec();
        System.out.println(response.getId());

        return response;
    }

    /**
     * 停止容器
     * @param containerId 容器id
     */
    public static void stopContainer(DockerClient dockerClient,String containerId) {
        dockerClient.stopContainerCmd(containerId).exec();

    }
    /**
     * 删除容器
     * @param containerId 容器id
     */
    public static void rmContainer(DockerClient dockerClient,String containerId){
        dockerClient.removeContainerCmd(containerId).exec();
    }

    /**
     * repository 镜像名称:tag名称
     **/
    public static void pullImage(DockerClient client, String repository)  {

        client.pullImageCmd(repository);

    }


    /**
     * 判断镜像是否存在
     * @param imageName 判断容器是否存在
     * @return 布尔
     */
    public static boolean existContainer(DockerClient client,String imageName){
        boolean existFlag = false;
        List<Image> images = client.listImagesCmd().withImageNameFilter("busybox").exec();

        if (images.isEmpty()) existFlag = true;
        return existFlag;
    }

    /**
     * 判断容器是否启动
     * @param containerId 容器id
     * @return 启动成功true
     */
    public static Boolean getContainerState(DockerClient client, String containerId){
        boolean startState = true;
        InspectContainerResponse inspectContainerResponse = client.inspectContainerCmd(containerId).exec();
        String status = inspectContainerResponse.getState().getStatus();
        if (!Objects.equals(status, "running")){
            startState=false;
            log.info("容器启动失败,当前容器状态{}",status);
        }
        return startState;
    }


    /**
     * 创建网络
     * @param networkName 网络名
     * @return 网络id
     */
    public static String createNetwork(DockerClient client, String networkName){
        CreateNetworkResponse networkResponse = client.createNetworkCmd().withName(networkName).exec();
        return networkResponse.getId();
    }
    /**
     * 创建网络
     * @param networkId 网络id
     */
    private static void rmNetwork(DockerClient client, String networkId){
        client.removeContainerCmd(networkId).exec();
    }
}


